对一个对象或者数组这种引用类型的值进行复制可以分为浅复制和深复制,比如这样的一个对象
let obj={
a:1,
b:{
a:1,
b:2
},
c:3
}
很明显这个对象是存在两层的,obj[b]不是基本类型值,而是另一个对象。如果使用浅复制去拷贝这个对象的话,那么拷贝出来新的对象的b属性的值是原来对象b属性的引用地址,也就是说,如果改变源对象的b属性,新的对象也会受到影响,因为我们只使用浅复制拷贝了一层。
上面讲的就是浅复制,在实际应用中存在很严重的问题。所以我们一般复制对象都是用深复制,深复制不是简单的复制一层,而是遍历整个对象,一直到获取到的值不是引用类型,而是基本类型的时候才进行复制,这样就使得新的对象跟原来的对象完全是两个不同的对象了。
下面是我写的一个简单的深复制函数
let obj={
a:1,
b:{
a:1,
b:2
},
c:3
}
function deepClone(object){
let obj=new Object();
if(object instanceof Object){
// 说明是对象
for(let attr in object){
if(object.hasOwnProperty(attr)){
// 过滤基本类型值
if(typeof object[attr]!='object'||object[attr]==null){
obj[attr]=object[attr];
}else{
obj[attr]=deepClone(object[attr]);
}
}
}
}
return obj;
}
let obj2=deepClone(obj);
obj.b=1;
console.log(obj,obj2);
注意,这个函数是存在问题的,因为这个函数只能处理纯对象类型,也就是说属性中包含数组的对象该方法是无法处理的。
下面这里有一个方法是stackoverflow
上的答案,兼容了数组与对象的
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
还有一种比较抖机灵的做法就是
var cloneOfA = JSON.parse(JSON.stringify(a));
这种做法也是可以实现深复制,但是由于JSON.stringify()
方法在遇到undefined
值时会省略对应的属性,所以这个方法不太推荐使用,存在问题。
基于jQ的做法是这样的
var copiedObject = jQuery.extend({}, originalObject) // shallow copy浅复制
var copiedObject = jQuery.extend(true, {}, originalObject) // deep copy深复制
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。